package android.slc.box.core.controller;

import android.slc.box.core.utils.interference.HandlerInterferenceManager;
import android.slc.box.core.utils.interference.OnHandlerInterference;
import javafx.event.EventHandler;
import javafx.stage.WindowEvent;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author slc
 * @date 2022/09/27 上午 9:18
 */
public class EventPlusHandler implements EventHandler<WindowEvent> {

    private final HandlerInterferenceManager<EventPlusHandlerListener, WindowEvent> handlerInterferenceManager = new HandlerInterferenceManager<>();
    private boolean listenerTraverseSpecies = false;
    private final List<AwaitEventPlusHandlerListener> awaitEventPlusHandlerListenerList = new ArrayList<>();

    /**
     * 添加窗口关闭监听
     * 此处 synchronized 可以不要
     * @param eventPlusHandlerListener
     */
    public synchronized void addEventPlusHandlerListener(EventPlusHandlerListener eventPlusHandlerListener) {
        if (listenerTraverseSpecies) {
            awaitEventPlusHandlerListenerList.add(new AwaitEventPlusHandlerListener(eventPlusHandlerListener, AwaitEventPlusHandlerListener.AwaitEventType.ADD));
            return;
        }
        handlerInterferenceManager.add(eventPlusHandlerListener);
    }

    /**
     * 移除窗口关闭监听
     * 此处 synchronized 可以不要
     * @param eventPlusHandlerListener
     */
    public synchronized void removeEventPlusHandlerListener(EventPlusHandlerListener eventPlusHandlerListener) {
        if (listenerTraverseSpecies) {
            awaitEventPlusHandlerListenerList.add(new AwaitEventPlusHandlerListener(eventPlusHandlerListener, AwaitEventPlusHandlerListener.AwaitEventType.REMOVE));
            return;
        }
        handlerInterferenceManager.remove(eventPlusHandlerListener);
    }

    /**
     * 通知
     *
     * @param event
     */
    private synchronized void notifyHandle(WindowEvent event) {
        if (event.isConsumed()) {
            return;
        }
        //监听迭代
        listenerTraverseSpecies = true;
        //按照优先级排序
        Iterator<EventPlusHandlerListener> eventPlusHandlerListenerListIterator = handlerInterferenceManager.iterator();
        EventPlusHandlerListener eventPlusHandlerListener;
        while (eventPlusHandlerListenerListIterator.hasNext()) {
            //获取下一个监听进行处理
            eventPlusHandlerListener = eventPlusHandlerListenerListIterator.next();
            if (!event.isConsumed()) {
                boolean listenerStatus = eventPlusHandlerListener.handle(event);
                if (listenerStatus) {
                    eventPlusHandlerListenerListIterator.remove();
                }
            } else if (eventPlusHandlerListener.consumedIsListener()) {
                eventPlusHandlerListener.handle(event);
            }
        }
        for (AwaitEventPlusHandlerListener awaitEventPlusHandlerListener : awaitEventPlusHandlerListenerList) {
            switch (awaitEventPlusHandlerListener.awaitEventType) {
                case ADD:
                    handlerInterferenceManager.add(awaitEventPlusHandlerListener.eventPlusHandlerListener);
                    break;
                case REMOVE:
                    handlerInterferenceManager.remove(awaitEventPlusHandlerListener.eventPlusHandlerListener);
                    break;
            }
        }
        //遍历完清除
        awaitEventPlusHandlerListenerList.clear();
        listenerTraverseSpecies = false;
    }

    @Override
    public void handle(WindowEvent event) {
        notifyHandle(event);
    }

    /**
     * 窗口关闭监听
     */
    public interface EventPlusHandlerListener extends OnHandlerInterference<WindowEvent> {

        /**
         * 被消耗了是否也监听
         *
         * @return
         */
        default boolean consumedIsListener() {
            return false;
        }
    }

    public static class AwaitEventPlusHandlerListener {
        private final EventPlusHandlerListener eventPlusHandlerListener;
        private final AwaitEventType awaitEventType;

        public AwaitEventPlusHandlerListener(EventPlusHandlerListener eventPlusHandlerListener, AwaitEventType awaitEventType) {
            this.eventPlusHandlerListener = eventPlusHandlerListener;
            this.awaitEventType = awaitEventType;
        }

        public EventPlusHandlerListener getEventPlusHandlerListener() {
            return eventPlusHandlerListener;
        }

        public AwaitEventType getAwaitEventType() {
            return awaitEventType;
        }

        public enum AwaitEventType {
            ADD,
            REMOVE
        }
    }
}
